package com.example.rabbit.consumer.config;

import com.example.rabbit.consumer.dto.UserDTO;
import org.springframework.cloud.function.context.PollableBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.scheduling.annotation.Scheduled;

import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

// Spring Cloud Stream 对 Spring Cloud Function 的集成配置注意事项，https://docs.springjava.cn/spring-cloud-stream/reference/spring-cloud-stream/producing-and-consuming-messages.html
@Configuration
public class FunctionConfig {

    // 由于在配置文件中配置 binding 名称，因此这些函数式消费者可以直接监听对应的消息通道
    // 参考 https://docs.springjava.cn/spring-cloud-stream/reference/spring-cloud-stream/bindings.html
    @Bean
    public Consumer<String> stringConsumer() {
        return System.out::println;
    }

    // 消费函数
    // @PollableBean 是Spring Cloud Stream中的一个注解，用于标记一个bean为可轮询的。这个注解主要用于那些需要从消息中间件接收消息的消费者bean，
    // 这些消费者可以定期轮询消息队列以获取新的消息。@PollableBean 注解提供了一种机制，允许消费者定期检查消息队列以获取待处理的消息。
    @PollableBean
    public Consumer<String> sink() {
        return System.out::println;
    }


    // 单个应用程序中的多个函数，
    // 您可能还需要在一个应用程序中对多个消息处理程序进行分组。您可以通过定义多个函数来做到这一点。
    @Bean
    public Function<String, String> uppercase() {
        // 这里的 value 就是消息，不用通过参数传入
        return value -> value.toUpperCase();
    }

    @Bean
    public Function<String, String> reverse() {
        return value -> new StringBuilder(value).reverse().toString();
    }
    // 在上面的示例中，我们有一个配置，它定义了两个函数uppercase和reverse。因此，首先，正如之前提到的，我们需要注意到存在冲突（多个函数），
    // 因此我们需要通过提供spring.cloud.function.definition属性来解决它，该属性指向我们要绑定的实际函数。除了这里我们将使用;分隔符来指向这两个函数
    // spring.cloud.function.definition=uppercase;reverse


    // 批处理消费者，参考官方 https://docs.springjava.cn/spring-cloud-stream/reference/spring-cloud-stream/producing-and-consuming-messages.html
    // 当使用支持批处理侦听器的MessageChannelBinder时，并且为消费者绑定启用了该功能，
    // 您可以将spring.cloud.stream.bindings.<binding-name>.consumer.batch-mode设置为true以启用将整个消息批次传递给函数中的List。
    @Bean
    public Function<List<UserDTO>, UserDTO> findFirstPerson() {
        return persons -> persons.getFirst();
    }

}

// 在 Spring Cloud Function 被其他框架（如 Spring Cloud Stream）用作编程模型的典型集成案例中，您需要通过 spring.cloud.function.definition 属性声明要使用哪些函数。
// spring.cloud.function.definition=uppercase,reverse

// 过滤不符合条件的功能
// spring.cloud.function.ineligible-definitions=foo,bar

// Spring Cloud Stream 对 Spring Cloud Function 的集成配置注意事项，https://docs.springjava.cn/spring-cloud-stream/reference/spring-cloud-stream/producing-and-consuming-messages.html
// Spring Cloud Function 文档参考   https://docs.spring.io/spring-cloud-function/reference/index.html
// Spring Cloud Stream 配置参考 https://docs.springjava.cn/spring-cloud-stream/reference/spring-cloud-stream.html
// Function 和 Consumer 的调用触发方式非常简单。它们是根据发送到绑定目标 destination 的数据（事件）触发的。换句话说，它们是典型的事件驱动组件。
// 不过，就触发而言，Supplier 属于自己的类别。顾名思义，它是数据的来源（原点），它不订阅任何绑定目的地 destination，因此必须由其他机制触发。
// 此外，还有一个供应商实施的问题，它可以是命令式的，也可以是反应式的，直接关系到这些供应商的触发问题。

// docker pull rabbitmq
// docker run -d --hostname rabbitmq --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:latest
// docker exec -it rabbitmq rabbitmq-plugins enable rabbitmq_management         // 开启管理插件
// docker exec -it rabbitmq rabbitmqctl add_user guest guest                     // 添加用户 guest
// 浏览器访问 http://192.168.56.10:15672/

// 如果出现 All stable feature flags must be enabled after completing an upgrade
//登录 RabbitMQ 的管理界面，导航到 “Admin” -> “Feature Flags”，确保所有稳定的特性标志都是启用状态。如果有任何标志未启用，请将其启用。